/**
 * 批注前端逻辑（MVP）
 * - 文本选区添加批注（存储 text-quote 锚点）
 * - 批注列表展示与定位
 * - 在内容详情容器(#contentViewContainer)渲染后自动初始化
 */
(function () {
  let state = {
    contentId: null,
    container: null,
    addBtn: null,
    selectionText: '',
    selectionEvent: null,
    notePanel: null,
    noteTextarea: null,
    currentAnchor: null,  // 存储当前选区的锚点信息
    replyToAnnotationId: null, // 当前正在回复的批注ID

    annModalOpen: false,
    annModalInst: null,
    selChangeBound: false
  };

  function $(id) { return document.getElementById(id); }

  function ensureButton() {
    if (state.addBtn) return;
    const btn = document.createElement('button');
    btn.type = 'button';
    btn.textContent = '添加批注';
    btn.style.position = 'fixed';
    btn.style.zIndex = '2147483647';
    btn.style.display = 'none';
    btn.style.padding = '6px 10px';
    btn.style.fontSize = '12px';
    btn.style.background = '#0d6efd';
    btn.style.color = '#fff';
    btn.style.border = 'none';
    btn.style.borderRadius = '4px';
    btn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';
    btn.addEventListener('click', onAddAnnotationClick);
    document.body.appendChild(btn);
    state.addBtn = btn;

    // 点击页面其他区域隐藏
    document.addEventListener('mousedown', (e) => {
      if (e.target !== btn) hideButton();
    });
  }

  // 漂浮输入面板：创建/显示/隐藏/提交
  function ensureNotePanel() {
    if (state.notePanel) return;
    const panel = document.createElement('div');
    panel.style.position = 'fixed';
    panel.style.zIndex = '2147483647';
    panel.style.display = 'none';
    panel.style.width = '280px';
    panel.style.maxWidth = '90vw';
    panel.style.background = '#fff';
    panel.style.border = '1px solid #dee2e6';
    panel.style.borderRadius = '0.5rem';
    panel.style.boxShadow = '0 8px 24px rgba(0,0,0,0.15)';
    panel.style.padding = '10px';
    panel.style.fontSize = '14px';

    // 内容
    const title = document.createElement('div');
    title.className = 'mb-2';
    title.innerHTML = '<strong>添加批注</strong>';
    const ta = document.createElement('textarea');
    ta.className = 'form-control form-control-sm';
    ta.rows = 6;
    ta.placeholder = '在此输入你的批注...';
    ta.style.resize = 'vertical';

    const actions = document.createElement('div');
    actions.className = 'mt-2 d-flex justify-content-end gap-2';

    const cancelBtn = document.createElement('button');
    cancelBtn.type = 'button';
    cancelBtn.className = 'btn btn-sm btn-outline-secondary';
    cancelBtn.textContent = '取消';
    cancelBtn.addEventListener('click', hideNotePanel);

    const saveBtn = document.createElement('button');
    saveBtn.type = 'button';
    saveBtn.className = 'btn btn-sm btn-primary';
    saveBtn.textContent = '保存';
    saveBtn.addEventListener('click', () => submitAnnotation(ta.value));

    // 键盘：Esc 取消，Ctrl+Enter 提交
    ta.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        hideNotePanel();
      } else if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
        e.preventDefault();
        submitAnnotation(ta.value);
      }
    });

    actions.appendChild(cancelBtn);
    actions.appendChild(saveBtn);

    panel.appendChild(title);
    panel.appendChild(ta);
    panel.appendChild(actions);

    panel.addEventListener('mousedown', (e) => e.stopPropagation());
    document.addEventListener('mousedown', (e) => {
      if (panel.style.display !== 'none' && !panel.contains(e.target)) {
        hideNotePanel();
      }
    });

    const host = document.getElementById('contentViewModal') || document.body;
    host.appendChild(panel);
    state.notePanel = panel;
    state.noteTextarea = ta;
  }

  function showNotePanelAt(x, y) {
    ensureNotePanel();
    const panel = state.notePanel;
    const ta = state.noteTextarea;
    if (!panel || !ta) return;

    // 显示批注输入提示
    const anchor = state.currentAnchor || anchorFromSelection();
    let contextInfo = '';
    if (anchor) {
      contextInfo = '请输入批注内容:' + String.fromCharCode(10);
    }

    ta.value = contextInfo;
    panel.style.display = 'block';

    // 基础定位
    let left = Math.max(8, x + 10);
    let top = Math.max(8, y + 10);

    // 避免出界（需要尺寸，先显示后测量）
    const vw = window.innerWidth;
    const vh = window.innerHeight;
    const rect = panel.getBoundingClientRect();
    if (left + rect.width + 8 > vw) left = Math.max(8, vw - rect.width - 8);
    if (top + rect.height + 8 > vh) top = Math.max(8, vh - rect.height - 8);

    panel.style.left = left + 'px';
    panel.style.top = top + 'px';

    // 聚焦
    setTimeout(() => ta.focus(), 0);
  }

  function hideNotePanel() {
    if (state.notePanel) state.notePanel.style.display = 'none';
    if (state.noteTextarea) state.noteTextarea.value = '';
    // 清除当前锚点信息
    state.currentAnchor = null;
  }

  async function submitAnnotation(note) {
    hideButton();
    const txt = String(note || '').trim();
    if (!state.selectionText) return;
    
    // 提取实际的批注内容（去掉上下文信息）
    const lines = txt.split(String.fromCharCode(10));
    let actualNote = '';
    let foundContentStart = false;
    
    for (let line of lines) {
      if (line.includes('请输入批注内容:')) {
        foundContentStart = true;
        continue;
      }
      if (foundContentStart && line.trim()) {
        actualNote += line + String.fromCharCode(10);
      }
    }
    
    actualNote = actualNote.trim();
    if (!actualNote) { alert('请输入批注内容'); return; }

    try {
      // 使用保存的锚点信息，而不是重新获取
      const anchor = state.currentAnchor || anchorFromSelection();
      
      const res = await fetch(`/api/content/${state.contentId}/annotations`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          note: actualNote,
          anchor: anchor
        })
      });
      const data = await res.json();
      if (!res.ok || data.error) {
        alert(data.error || '创建批注失败');
        return;
      }
      hideNotePanel();
      await loadAnnotations();
    } catch (e) {
      console.error('创建批注失败:', e);
      alert('创建批注失败');
    }
  }

  function showButtonAt(x, y) {
    ensureButton();
    state.addBtn.style.left = Math.max(8, x + 10) + 'px';
    state.addBtn.style.top = Math.max(8, y + 10) + 'px';
    state.addBtn.style.display = 'inline-block';
  }

  function hideButton() {
    if (state.addBtn) state.addBtn.style.display = 'none';
  }

  function bindSelection() {
    if (!state.container) return;
    state.container.addEventListener('mouseup', (e) => {
      const sel = window.getSelection();
      if (!sel || sel.isCollapsed || !sel.rangeCount) { hideButton(); return; }
      const range = sel.getRangeAt(0);
      if (!state.container.contains(range.commonAncestorContainer)) { hideButton(); return; }
      const text = (sel.toString() || '').trim();
      if (!text) { hideButton(); return; }
      state.selectionText = text;
      state.selectionEvent = e;
      // 立即保存当前选区的锚点信息
      state.currentAnchor = anchorFromSelection();
      showButtonAt(e.clientX, e.clientY);
      // 用选区矩形再校正一次位置，保证按钮紧邻选区
      setTimeout(() => {
        const rect = range.getBoundingClientRect();
        const x = (rect.right || rect.left);
        const y = (rect.bottom || rect.top);
        state.selectionEvent = { clientX: x, clientY: y };
        if (state.selectionText) showButtonAt(x, y);
      }, 0);
    });
    // 兜底：处理键盘/双击等导致的选区变更
    if (!state.selChangeBound) {
      state.selChangeBound = true;
      document.addEventListener('selectionchange', () => {
        setTimeout(() => {
          const sel2 = window.getSelection();
          if (!sel2 || sel2.isCollapsed || !sel2.rangeCount) { hideButton(); return; }
          const r2 = sel2.getRangeAt(0);
          if (!state.container || !state.container.contains(r2.commonAncestorContainer)) { hideButton(); return; }
          const t2 = (sel2.toString() || '').trim();
          if (!t2) { hideButton(); return; }
          const rect2 = r2.getBoundingClientRect();
          const x2 = (rect2.right || rect2.left);
          const y2 = (rect2.bottom || rect2.top);
          state.selectionText = t2;
          state.selectionEvent = { clientX: x2, clientY: y2 };
          showButtonAt(x2, y2);
        }, 0);
      });
    }
  }

  // 计算文本节点在容器中的绝对字符偏移量
  function calculateTextOffset(node, container) {
    if (!node || !container) return 0;
    
    let offset = 0;
    const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);
    
    while (walker.nextNode()) {
      const currentNode = walker.currentNode;
      if (currentNode === node) break;
      offset += currentNode.textContent.length;
    }
    
    return offset;
  }
  
  function anchorFromSelection() {
    // 增强锚点信息：保存选中文本及其前后文上下文和字符偏移量
    const selection = window.getSelection();
    if (!selection.rangeCount) return null;
    
    const range = selection.getRangeAt(0);
    const container = range.commonAncestorContainer;
    
    // 获取选中文本前后的上下文（各50个字符）
    let prefix = '';
    let suffix = '';
    
    try {
      // 扩展范围获取前文
      const prefixRange = range.cloneRange();
      prefixRange.setStart(container.nodeType === Node.TEXT_NODE ? container : container.firstChild || container, 0);
      prefixRange.setEnd(range.startContainer, range.startOffset);
      const prefixText = prefixRange.toString();
      prefix = prefixText.slice(-50); // 取最后50个字符
      
      // 扩展范围获取后文
      const suffixRange = range.cloneRange();
      suffixRange.setStart(range.endContainer, range.endOffset);
      suffixRange.setEnd(container.nodeType === Node.TEXT_NODE ? container : container.lastChild || container, 
                        container.nodeType === Node.TEXT_NODE ? container.textContent.length : container.textContent.length);
      const suffixText = suffixRange.toString();
      suffix = suffixText.slice(0, 50); // 取前50个字符
    } catch (e) {
      // 如果获取上下文失败，使用简单的文本节点方式
      const textNode = range.startContainer;
      if (textNode.nodeType === Node.TEXT_NODE) {
        const fullText = textNode.textContent;
        const startOffset = range.startOffset;
        const endOffset = range.endOffset;
        prefix = fullText.slice(Math.max(0, startOffset - 50), startOffset);
        suffix = fullText.slice(endOffset, Math.min(fullText.length, endOffset + 50));
      }
    }
    
    // 计算选中文本在容器中的绝对字符偏移量
    let startOffset = 0;
    let endOffset = 0;
    
    try {
      // 获取选中文本的起始和结束节点
      const startNode = range.startContainer;
      const endNode = range.endContainer;
      
      // 计算起始节点在容器中的绝对偏移量
      if (startNode.nodeType === Node.TEXT_NODE) {
        startOffset = calculateTextOffset(startNode, state.container) + range.startOffset;
      }
      
      // 计算结束节点在容器中的绝对偏移量
      if (endNode.nodeType === Node.TEXT_NODE) {
        endOffset = calculateTextOffset(endNode, state.container) + range.endOffset;
      }
    } catch (e) {
      console.warn('计算字符偏移量失败:', e);
    }
    
    return {
      method: 'text-quote',
      quote: state.selectionText,
      context_before: prefix,
      context_after: suffix,
      // 添加字符偏移量信息
      start_offset: startOffset,
      end_offset: endOffset,
      content_length: state.container ? state.container.textContent.length : 0
    };
  }

  async function onAddAnnotationClick() {
    hideButton();
    if (!state.selectionText) return;
    ensureNotePanel();
    const ev = state.selectionEvent;
    const x = ev && (ev.clientX ?? ev.pageX) ? (ev.clientX ?? ev.pageX) : (window.innerWidth / 2);
    const y = ev && (ev.clientY ?? ev.pageY) ? (ev.clientY ?? ev.pageY) : (window.innerHeight / 2);
    showNotePanelAt(x, y);
  }

  async function loadAnnotations() {
    if (!state.contentId) return;
    try {
      const res = await fetch(`/api/content/${state.contentId}/annotations`);
      const data = await res.json();
      if (!res.ok || data.error) {
        console.warn('加载批注失败', data.error);
        return;
      }
      renderHighlights(data.annotations || []);
      renderPanel(data.annotations || []);
    } catch (e) {
      console.error('加载批注失败:', e);
    }
  }

  function parseAnchor(anchor_json) {
    if (!anchor_json) return null;
    if (typeof anchor_json === 'object') return anchor_json;
    try { return JSON.parse(anchor_json); } catch { return null; }
  }

  function renderHighlights(annotations) {
    if (!state.container) return;
    // 简单高亮：按顺序为每条批注的 quote 包一层 span
    annotations.forEach((ann) => {
      const anchor = parseAnchor(ann.anchor_json);
      if (!anchor || anchor.method !== 'text-quote' || !anchor.quote) return;
      wrapBestMatch(state.container, anchor, ann.id);
    });
  }

  function wrapBestMatch(root, anchor, id) {
    if (!anchor || !anchor.quote) return null;
    
    const text = anchor.quote;
    const prefix = anchor.context_before || '';
    const suffix = anchor.context_after || '';
    const startOffset = anchor.start_offset || 0;
    const endOffset = anchor.end_offset || 0;
    
    // 首先尝试使用字符偏移量定位
    if (startOffset > 0 && endOffset > startOffset) {
      try {
        const result = findNodeByCharOffset(root, startOffset, endOffset - startOffset);
        if (result) {
          const { node, offset } = result;
          try {
            const range = document.createRange();
            range.setStart(node, offset);
            range.setEnd(node, offset + text.length);
            const span = document.createElement('span');
            span.className = 'annotation-highlight';
            span.style.backgroundColor = 'yellow';
            span.style.padding = '0 2px';
            span.style.cursor = 'pointer';
            if (id) span.id = 'ann-' + id;
            range.surroundContents(span);
            return span;
          } catch (e) {
            console.warn('使用字符偏移量高亮失败，尝试使用文本匹配:', e);
          }
        }
      } catch (e) {
        console.warn('字符偏移量定位失败，尝试使用文本匹配:', e);
      }
    }
    
    // 如果字符偏移量定位失败，回退到文本匹配方法
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
    let bestMatch = null;
    let bestScore = -1;
    
    let node;
    while ((node = walker.nextNode())) {
      if (!node.nodeValue || !node.nodeValue.trim()) continue;
      
      const nodeText = node.nodeValue;
      let idx = nodeText.indexOf(text);
      
      while (idx !== -1) {
        // 计算匹配分数
        let score = 0;
        
        // 检查前文匹配
        if (prefix) {
          const beforeText = nodeText.slice(Math.max(0, idx - prefix.length), idx);
          const prefixMatch = calculateSimilarity(beforeText, prefix);
          score += prefixMatch * 0.5;
        }
        
        // 检查后文匹配
        if (suffix) {
          const afterText = nodeText.slice(idx + text.length, idx + text.length + suffix.length);
          const suffixMatch = calculateSimilarity(afterText, suffix);
          score += suffixMatch * 0.5;
        }
        
        // 如果没有上下文信息，使用第一个匹配
        if (!prefix && !suffix) {
          score = 1;
        }
        
        if (score > bestScore) {
          bestScore = score;
          bestMatch = { node, idx };
        }
        
        // 查找下一个匹配
        idx = nodeText.indexOf(text, idx + 1);
      }
    }
    
    // 高亮最佳匹配
    if (bestMatch) {
      try {
        const range = document.createRange();
        range.setStart(bestMatch.node, bestMatch.idx);
        range.setEnd(bestMatch.node, bestMatch.idx + text.length);
        const span = document.createElement('span');
        span.className = 'annotation-highlight';
        span.style.backgroundColor = 'yellow';
        span.style.padding = '0 2px';
        span.style.cursor = 'pointer';
        if (id) span.id = 'ann-' + id;
        range.surroundContents(span);
        return span;
      } catch (e) {
        // 如果跨节点，降级为不高亮
        console.warn('无法高亮跨节点文本:', e);
      }
    }
    
    return null;
  }
  
  // 根据字符偏移量查找对应的文本节点和节点内偏移量
  function findNodeByCharOffset(container, targetOffset, length) {
    if (!container) return null;
    
    let currentOffset = 0;
    const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);
    
    while (walker.nextNode()) {
      const node = walker.currentNode;
      const nodeLength = node.textContent.length;
      
      // 如果当前节点包含目标偏移量
      if (currentOffset + nodeLength > targetOffset) {
        const offset = targetOffset - currentOffset;
        // 确保节点内有足够的文本长度
        if (offset + length <= nodeLength) {
          return { node, offset };
        }
      }
      
      currentOffset += nodeLength;
    }
    
    return null;
  }
  
  // 计算两个字符串的相似度（简单的字符匹配）
  function calculateSimilarity(str1, str2) {
    if (!str1 || !str2) return 0;
    if (str1 === str2) return 1;
    
    const longer = str1.length > str2.length ? str1 : str2;
    const shorter = str1.length > str2.length ? str2 : str1;
    
    if (longer.length === 0) return 1;
    
    let matches = 0;
    for (let i = 0; i < shorter.length; i++) {
      if (longer.includes(shorter[i])) matches++;
    }
    
    return matches / longer.length;
  }

  function renderPanel(annotations) {
    return;
  }

  function renderDeleteButton(ann) {
    try {
      // 检查当前用户是否是批注作者
      if (window.currentUser && String(window.currentUser.user_id) === String(ann.user_id)) {
        return `<button class="btn btn-sm btn-outline-danger" data-del="${ann.id}">删除</button>`;
      }
    } catch (e) {
      // 静默处理权限检查错误
    }
    return '';
  }

  function escapeHtml(s) {
    const str = String(s ?? '');
    const map = {
      '&': '&#38;',
      '<': '&#60;',
      '>': '&#62;',
      '\"': '&#34;',
      "'": '&#39;',
      '`': '&#96;'
    };
    return str.replace(/[&<>"'`]/g, ch => map[ch]);
  }

  async function refreshContent() {
    // 简易刷新：清空并重新加载批注（避免重复包裹）
    if (!state.container) return;
    // 还原内容文本：因为我们仅在内容上包裹span，无法轻易反向移除
    // 所以仅重新打开内容时自然刷新。这里仅刷新批注列表并尝试再次高亮剩余位置。
    // 为不干扰原内容，这里只重新加载批注并试图为未高亮的quote再包裹一次。
    await loadAnnotations();
  }

  function init(contentId) {
    state.contentId = contentId;
    state.container = $('contentViewContainer');
    if (!state.container) return;
    ensureButton();
    bindSelection();
    loadAnnotations();
  }

  // 监听内容详情弹窗打开后初始化
  document.addEventListener('DOMContentLoaded', function () {
    const modal = $('contentViewModal');
    if (modal) {
      modal.addEventListener('shown.bs.modal', () => {
        const cid = window.currentContentId || null;
        if (cid) {
          setTimeout(() => init(cid), 0);
        }
        setTimeout(() => openAnnotationsModal(), 0);
      });
      modal.addEventListener('hidden.bs.modal', () => {
        const ann = document.getElementById('annotationsModal');
        if (ann) {
          if (state.annModalInst) {
            try { state.annModalInst.hide(); } catch {}
          } else {
            ann.classList.remove('show');
            ann.style.display = 'none';
          }
        }
        state.annModalOpen = false;
        // 恢复详情弹窗位移
        const hostDialog = modal.querySelector('.modal-dialog') || modal;
        if (hostDialog) {
          hostDialog.style.transform = '';
        }
      });
    }
    
    // 注意：使用script.js中已定义的showUserProfile函数
  });
  // ensureSidebarLayout 已删除（侧栏方案已废弃）

  // 批注独立模态窗口（Bootstrap Modal）
  function ensureAnnotationsModal() {
    let modalEl = document.getElementById('annotationsModal');
    if (!modalEl) {
      const wrapper = document.createElement('div');
      wrapper.innerHTML =
        '<div class="modal" id="annotationsModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="false" data-bs-keyboard="false">' +
        '  <div class="modal-dialog modal-dialog-scrollable" style="width: 360px; max-width: 90vw; margin: 0;">' +
        '    <div class="modal-content">' +
        '      <div class="modal-header">' +
        '        <h5 class="modal-title">批注</h5>' +
        '        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>' +
        '      </div>' +
        '      <div class="modal-body">' +
        '        <div id="annModalList"></div>' +
        '      </div>' +
        '    </div>' +
        '  </div>' +
        '</div>';
      document.body.appendChild(wrapper.firstElementChild);

      modalEl = document.getElementById('annotationsModal');
      // 提高层级，避免被内容详情Modal遮挡
      modalEl.style.zIndex = '1062';
      // 只让对话框可点，容器不拦截事件，避免遮挡详情
      modalEl.style.pointerEvents = 'none';
      { const d = modalEl.querySelector('.modal-dialog'); if (d) d.style.pointerEvents = 'auto'; }
      // 窗口尺寸变化时重定位，保持批注始终在左侧
      if (!window.__annPosBound) {
        window.addEventListener('resize', positionAnnotationsModal);
        window.__annPosBound = true;
      }

      modalEl.addEventListener('shown.bs.modal', () => {
        state.annModalOpen = true;
        loadAnnotationsForModal();
        setTimeout(positionAnnotationsModal, 0);
      });
      modalEl.addEventListener('hidden.bs.modal', () => {
        state.annModalOpen = false;
      });



    }

    if (!state.annModalInst && window.bootstrap && window.bootstrap.Modal) {
      // 保持批注Modal不因点击外部或按Esc而关闭
      state.annModalInst = new bootstrap.Modal(modalEl, { backdrop: false, keyboard: false, focus: false });
    }
    return modalEl;
  }

  function openAnnotationsModal() {
    const el = ensureAnnotationsModal();
    if (state.annModalInst) state.annModalInst.show();
    else el.classList.add('show'); // 兜底
  }

  async function loadAnnotationsForModal() {
    if (!state.contentId) return;
    try {
      const res = await fetch(`/api/content/${state.contentId}/annotations`);
      const data = await res.json();
      if (!res.ok || data.error) return;
      renderModalList(data.annotations || []);
    } catch (e) {
      console.error('加载批注失败:', e);
    }
  }

  // 创建回复输入框
  function createReplyForm(annotationId) {
    const form = document.createElement('div');
    form.className = 'mt-2 reply-form';
    
    // 使用DOM API创建元素，而不是innerHTML，避免可能的事件绑定问题
    const textarea = document.createElement('textarea');
    textarea.className = 'form-control form-control-sm mb-2';
    textarea.placeholder = '写回复...';
    textarea.rows = 2;
    
    const btnContainer = document.createElement('div');
    btnContainer.className = 'd-flex justify-content-end';
    
    const sendBtn = document.createElement('button');
    sendBtn.type = 'button';
    sendBtn.className = 'btn btn-primary btn-sm me-2';
    sendBtn.textContent = '发送';
    
    const cancelBtn = document.createElement('button');
    cancelBtn.type = 'button';
    cancelBtn.className = 'btn btn-outline-secondary btn-sm';
    cancelBtn.textContent = '取消';
    
    btnContainer.appendChild(sendBtn);
    btnContainer.appendChild(cancelBtn);
    
    form.appendChild(textarea);
    form.appendChild(btnContainer);
    
    sendBtn.addEventListener('click', async () => {
      const replyText = textarea.value.trim();
      if (!replyText) return;
      
      try {
        const res = await fetch(`/api/annotations/${annotationId}/replies`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: replyText })
        });
        
        const data = await res.json();
        if (!res.ok || data.error) {
          alert(data.error || '回复失败');
          return;
        }
        
        // 刷新批注列表
        await loadAnnotationsForModal();
        textarea.value = '';
      } catch (e) {
        console.error('回复失败:', e);
        alert('回复失败');
      }
    });
    
    cancelBtn.addEventListener('click', () => {
      form.remove();
      state.replyToAnnotationId = null;
    });
    
    return form;
  }
  
  // 格式化日期显示
  function formatDate(dateStr) {
    if (!dateStr) return '';
    try {
      return new Date(dateStr).toLocaleString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit'
      });
    } catch (e) {
      return dateStr;
    }
  }

  // 渲染批注回复
  async function renderAnnotationReplies(annotationId, container) {
    try {
      const res = await fetch(`/api/annotations/${annotationId}/replies`);
      const data = await res.json();
      
      if (!res.ok || data.error) {
        console.warn('加载回复失败:', data.error);
        return;
      }
      
      const replies = data.replies || [];
      if (!replies.length) {
        container.innerHTML = '';
        return;
      }
      
      // 按照时间顺序排序回复
      const sortedReplies = replies.sort((a, b) => 
        new Date(a.created_at || a.timestamp || 0) - new Date(b.created_at || b.timestamp || 0)
      );
      
      let html = '<div class="replies mt-2">';
      sortedReplies.forEach(reply => {
        const replyContent = reply.reply || reply.content || '';
        const timestamp = reply.created_at || reply.timestamp || '';
        const formattedDate = formatDate(timestamp);
        
        html += `
          <div class="comment-item mb-2 p-2 border-start border-3" 
               style="border-color: #3b82f6 !important; background-color: #f8f9fa; margin-left: 30px;" 
               data-reply-id="${reply.id}">
            <div class="d-flex justify-content-between align-items-center mb-1">
              <div>
                <a href="javascript:void(0)" onclick="showUserProfile(${reply.user_id})" 
                   class="user-link fw-bold">${escapeHtml(reply.username || '')}</a>
                <small class="text-muted ms-2">${formattedDate}</small>
              </div>
              <div>
                ${reply.user_id === (window.currentUser?.user_id || 0) ? 
                  `<a href="javascript:void(0)" class="text-danger small delete-reply" 
                     data-reply-id="${reply.id}">删除</a>` : ''}
              </div>
            </div>
            <p class="mb-1">${escapeHtml(replyContent)}</p>
          </div>
        `;
      });
      html += '</div>';
      
      container.innerHTML = html;
      
      // 绑定删除回复事件
      container.querySelectorAll('.delete-reply').forEach(link => {
        link.addEventListener('click', async (e) => {
          e.preventDefault();
          const replyId = link.getAttribute('data-reply-id');
          if (!confirm('确定删除此回复？')) return;
          
          try {
            const res = await fetch(`/api/annotation-replies/${replyId}`, { method: 'DELETE' });
            const data = await res.json();
            
            if (!res.ok || data.error) {
              alert(data.error || '删除回复失败');
              return;
            }
            
            // 重新渲染回复
            await renderAnnotationReplies(annotationId, container);
          } catch (e) {
            console.error('删除回复失败:', e);
            alert('删除回复失败');
          }
        });
      });
    } catch (e) {
      console.error('加载回复失败:', e);
      container.innerHTML = '<div class="small text-danger mt-2">加载回复失败</div>';
    }
  }

  function renderModalList(arr) {
    const box = document.getElementById('annModalList');
    if (!box) return;
    if (!arr.length) {
      box.innerHTML = '<div class="small text-muted">暂无批注</div>';
      return;
    }
    let html = '';
    arr.forEach((ann) => {
      const anchor = parseAnchor(ann.anchor_json);
      const quote = anchor && anchor.quote ? anchor.quote : '';
      const annotationId = ann.id;
      
      html +=
        '<div class="border rounded p-2 mb-2" data-annotation-id="' + annotationId + '">' +
        ' <div class="d-flex justify-content-between align-items-center">' +
        '   <a href="javascript:void(0)" onclick="showUserProfile(' + ann.user_id + ')" class="user-link fw-bold">' + 
        escapeHtml(ann.username || '') + '</a>' +
        '   <div>' + (renderDeleteButton(ann)) + '</div>' +
        ' </div>' +
        ' <div class="text-muted small mb-1">' + 
        '<a href="javascript:void(0)" onclick="scrollToAnnotation(' + annotationId + ')" class="text-decoration-none text-muted">' + 
        escapeHtml(quote) + '</a></div>' +
        ' <div>' + escapeHtml(ann.note || '') + '</div>' +
        ' <div class="d-flex justify-content-end align-items-center mt-1">' +
        '   <button class="btn btn-sm btn-link reply-button" data-annotation-id="' + annotationId + '"><i class="bi bi-reply me-1"></i>回复</button>' +
        ' </div>' +
        ' <div class="replies-container" id="replies-' + annotationId + '"></div>' +
        '</div>';
    });
    box.innerHTML = html;

    // 加载每个批注的回复
    arr.forEach(ann => {
      const repliesContainer = box.querySelector(`#replies-${ann.id}`);
      if (repliesContainer) {
        renderAnnotationReplies(ann.id, repliesContainer);
      }
    });

    // 添加全局函数用于滚动到批注位置
    window.scrollToAnnotation = function(id) {
      const el = document.getElementById('ann-' + id);
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'center' });
        el.style.transition = 'box-shadow 0.3s';
        el.style.boxShadow = '0 0 0 2px #0d6efd';
        setTimeout(() => (el.style.boxShadow = 'none'), 1000);
      } else {
        alert('未找到对应位置（可能内容变化导致锚点失效）');
      }
    };

    // 绑定删除批注按钮事件
    box.querySelectorAll('[data-del]').forEach(btn => {
      btn.addEventListener('click', async () => {
        const id = btn.getAttribute('data-del');
        if (!confirm('确定删除该批注？')) return;
        try {
          const res = await fetch(`/api/annotations/${id}`, { method: 'DELETE' });
          const data = await res.json();
          if (!res.ok || data.error) {
            alert(data.error || '删除失败');
            return;
          }
          await loadAnnotationsForModal();
          await refreshContent();
        } catch (e) {
          console.error('删除失败:', e);
          alert('删除失败');
        }
      });
    });
    
    // 绑定回复按钮事件
    box.querySelectorAll('.reply-button').forEach(btn => {
      btn.addEventListener('click', (e) => {
        // 阻止事件冒泡，避免触发父元素的事件
        e.stopPropagation();
        
        const annotationId = btn.getAttribute('data-annotation-id');
        
        // 如果已经有回复表单，先移除
        const existingForm = box.querySelector('.reply-form');
        if (existingForm) {
          existingForm.remove();
          // 如果点击的是同一个批注的回复按钮，则仅关闭表单
          if (state.replyToAnnotationId === annotationId) {
            state.replyToAnnotationId = null;
            return;
          }
        }
        
        // 创建新的回复表单
        state.replyToAnnotationId = annotationId;
        const annotationEl = box.querySelector(`[data-annotation-id="${annotationId}"]`);
        const repliesContainer = annotationEl.querySelector('.replies-container');
        const replyForm = createReplyForm(annotationId);
        
        // 插入回复表单到回复容器的顶部
        if (repliesContainer.firstChild) {
          repliesContainer.insertBefore(replyForm, repliesContainer.firstChild);
        } else {
          repliesContainer.appendChild(replyForm);
        }
        
        // 聚焦输入框
        const textarea = replyForm.querySelector('textarea');
        setTimeout(() => textarea.focus(), 0);
      });
    });
  }

  function positionAnnotationsModal() {
    const modal = document.getElementById('annotationsModal');
    const host = document.getElementById('contentViewModal');
    if (!modal || !host) return;
    const hostDialog = host.querySelector('.modal-dialog') || host;
    const rect = hostDialog.getBoundingClientRect();
    const dlg = modal.querySelector('.modal-dialog');
    if (!dlg) return;
    const width = dlg.getBoundingClientRect().width || 360;
    const gap = 0;
    dlg.style.position = 'fixed';
    // 批注窗口固定在视图左侧
    const annLeft = 8;
    dlg.style.left = annLeft + 'px';
    dlg.style.top = rect.top + 'px';
    dlg.style.height = rect.height + 'px';
    dlg.style.margin = '0';
    // 将详情Modal整体右移，确保批注不遮挡且详情可点击（仅水平平移，不修改定位）
    if (hostDialog) {
      const hostRect = hostDialog.getBoundingClientRect();
      const annRect = dlg.getBoundingClientRect();
      const desiredLeft = Math.round(annRect.left + annRect.width + gap);
      const deltaX = desiredLeft - Math.round(hostRect.left);
      hostDialog.style.transform = `translateX(${deltaX}px)`;
    }
  }

})();